#pragma once

#include <QObject>
#include <QByteArray>
#include <cstdint>
#include <functional>
#include <memory>
#include "kernel/interfaces/ILogger.h"

namespace application {
namespace auto_door {

/**
 * @brief LED控制协议消息类型
 * @details 对应 led_control_protocol.md 中定义的 MsgType
 */
enum class LedMsgType : uint8_t {
    LED_CONTROL     = 0x10,  // 主机→设备：控制LED
    LED_ACK         = 0x80,  // 设备→主机：LED控制确认
    LED_ERROR       = 0x81,  // 设备→主机：LED控制错误
    HELLO           = 0x20,  // 设备→主机：上电握手
    HELLO_ACK       = 0xA0,  // 主机→设备：握手确认
    HEARTBEAT       = 0x21,  // 设备→主机：心跳
    HEARTBEAT_ACK   = 0xA1   // 主机→设备：心跳确认
};

/**
 * @brief LED控制协议错误码
 */
enum class LedErrorCode : uint8_t {
    NONE                = 0x00,  // 无错误
    INVALID_LENGTH      = 0x01,  // 载荷长度错误
    INVALID_LEVEL       = 0x02,  // LevelMask无效
    UNSUPPORTED_MSG     = 0x03,  // 不支持的消息类型
    VERSION_MISMATCH    = 0x04   // 版本不匹配
};

/**
 * @brief 协议帧结构
 */
struct LedProtocolFrame {
    // 帧头（固定）
    uint8_t preamble0{0xAA};
    uint8_t preamble1{0x55};

    // 帧信息
    uint8_t version{0x01};
    LedMsgType msgType{LedMsgType::LED_CONTROL};
    uint16_t payloadLength{0};
    uint16_t sequence{0};

    // 载荷
    QByteArray payload;

    // 校验
    uint16_t crc16{0};
};

/**
 * @brief HELLO 消息载荷
 */
struct HelloPayload {
    quint32 deviceId{0};       // 设备ID（4字节）
    uint16_t fwVersion{0};     // 固件版本
    uint8_t flags{0};          // 能力标志位
};

/**
 * @brief HEARTBEAT 消息载荷
 */
struct HeartbeatPayload {
    quint32 deviceId{0};       // 设备ID（4字节）
    uint32_t uptime{0};        // 运行时间（毫秒）
};

/**
 * @brief LED_CONTROL 消息载荷
 */
struct LedControlPayload {
    uint32_t programId{0};     // 业务指令编号（4字节）
    uint8_t levelMask{0};      // LED电平掩码（低3位）
};

/**
 * @brief LED_ACK/LED_ERROR 消息载荷
 */
struct LedResponsePayload {
    uint32_t programId{0};     // 回显业务指令编号
    uint8_t data{0};           // ACK时为levelMask，ERROR时为errorCode
};

/**
 * @brief LED控制协议类
 * @details 实现帧的编解码、CRC校验
 */
class AutoDoorProtocol : public QObject {
    Q_OBJECT

public:
    explicit AutoDoorProtocol(std::shared_ptr<kernel::ILogger> logger = nullptr, QObject* parent = nullptr);
    ~AutoDoorProtocol() = default;

    // ========== 编码方法（构建发送帧） ==========

    /**
     * @brief 构建 HELLO_ACK 帧
     */
    QByteArray buildHelloAck(quint32 deviceId, uint8_t result, uint16_t sequence = 0);

    /**
     * @brief 构建 HEARTBEAT_ACK 帧
     */
    QByteArray buildHeartbeatAck(quint32 deviceId, uint8_t result, uint16_t sequence = 0);

    /**
     * @brief 构建 LED_CONTROL 帧
     */
    QByteArray buildLedControl(uint32_t programId, uint8_t levelMask, uint16_t sequence = 0);

    // ========== 解码方法（解析接收帧） ==========

    /**
     * @brief 追加接收数据到缓冲区
     * @param data 新接收的数据
     */
    void appendData(const QByteArray& data);

    /**
     * @brief 尝试解析缓冲区中的完整帧
     * @return 是否成功解析一帧
     */
    bool parseFrame();

    /**
     * @brief 获取当前流水号并递增
     */
    uint16_t getNextSequence();

signals:
    /**
     * @brief 收到 HELLO 消息
     */
    void helloReceived(quint32 deviceId, uint16_t fwVersion, uint8_t flags, uint16_t sequence);

    /**
     * @brief 收到 HEARTBEAT 消息
     */
    void heartbeatReceived(quint32 deviceId, uint32_t uptime, uint16_t sequence);

    /**
     * @brief 收到 LED_ACK 消息
     */
    void ledAckReceived(uint32_t programId, uint8_t levelMask, uint16_t sequence);

    /**
     * @brief 收到 LED_ERROR 消息
     */
    void ledErrorReceived(uint32_t programId, LedErrorCode errorCode, uint16_t sequence);

    /**
     * @brief 协议错误（帧损坏、CRC错误等）
     */
    void protocolError(const QString& error);

private:
    // ========== 内部辅助方法 ==========

    /**
     * @brief 计算 CRC16-CCITT (false)
     * @param data 数据（从Version字段到Payload末尾）
     * @return CRC16校验值（大端）
     */
    uint16_t calculateCrc16(const QByteArray& data) const;

    /**
     * @brief 查找帧头
     * @return 帧头位置，-1表示未找到
     */
    int findPreamble() const;

    /**
     * @brief 从载荷中解析 HELLO 消息
     */
    void parseHello(const QByteArray& payload, uint16_t sequence);

    /**
     * @brief 从载荷中解析 HEARTBEAT 消息
     */
    void parseHeartbeat(const QByteArray& payload, uint16_t sequence);

    /**
     * @brief 从载荷中解析 LED_ACK 消息
     */
    void parseLedAck(const QByteArray& payload, uint16_t sequence);

    /**
     * @brief 从载荷中解析 LED_ERROR 消息
     */
    void parseLedError(const QByteArray& payload, uint16_t sequence);

    /**
     * @brief 构建通用帧
     */
    QByteArray buildFrame(LedMsgType msgType, const QByteArray& payload, uint16_t sequence);

private:
    QByteArray m_receiveBuffer;                  // 接收缓冲区
    uint16_t m_sequence{0};                      // 发送流水号
    std::shared_ptr<kernel::ILogger> m_logger;

    static constexpr int MAX_PAYLOAD_LENGTH = 16;  // 最大载荷长度
    static constexpr uint8_t PROTOCOL_VERSION = 0x01;
};

} // namespace auto_door
} // namespace application
